﻿using Sustainalytics.Entities.ProductInvolvement;
using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.Utils;

namespace Sustainalytics.ProductInvolvement.BL
{
    public class ProductInvolvementDataDto
    {
        public virtual Guid Id { get; set; }
        public virtual string CompanyName { get; set; }
        public virtual List<ProductInvolvementCompanyIndicatorDto> Indicators { get; set; }
        public virtual string Country { get; set; }
        public virtual string Industry { get; set; }
        public virtual string PeerGroupName { get; set; }
        public int CompanyId { get; set; }
        public string Exchange { get; set; }
        public string Ticker { get; set; }
        public double? MarketCap { get; set; }
        public double? Employees { get; set; }
        public string CompanyNameUrlSafe { get; set; }

        public static ProductInvolvementDataDto FromCompanyAssessment(ProductInvolvementData ca, IEnumerable<ProductInvolvementFramework> indicators, List<String> claimedIndicators = null)
        {
            var result = new ProductInvolvementDataDto()
            {
                Id = ca.Id,
                CompanyName = ca.CompanyName,
                Country = ca.Country,
                Industry = ca.Industry,
                CompanyId = ca.CompanyId,
                Exchange = ca.Exchange,
                Ticker = ca.Ticker,
                PeerGroupName = ca.PeerGroupName,
                MarketCap = ca.MarketCap,
                Employees = ca.Employees,
                CompanyNameUrlSafe = ca.CompanyNameSafeUrl                
            };

            result.Indicators = new List<ProductInvolvementCompanyIndicatorDto>();

            //or we can use https://code.google.com/p/morelinq/source/browse/MoreLinq/DistinctBy.cs
            var distinctSortedIndicators = ca.Indicators
              .GroupBy(x => x.IndicatorSymbol)
              .Select(grp => grp.First())
              .OrderBy(x => x.IndicatorSymbol);

            foreach (ProductInvolvementDataIndicator iass in distinctSortedIndicators)
            {
                ProductInvolvementCompanyIndicatorDto companyIndicatorDto = new ProductInvolvementCompanyIndicatorDto() { Symbol = iass.IndicatorSymbol };

                var indicator = indicators.FirstOrDefault(x => x.Symbol == iass.IndicatorSymbol);
                if (indicator == null)
                    throw new Exception($"Product Involvement indicator with symbol: {iass.IndicatorSymbol} could not be found.");

                if (iass.CategoryOfInvolvementType == "Not researched")
                {
                    result.Indicators.Add(new ProductInvolvementCompanyIndicatorDto()
                    {
                        Symbol = iass.IndicatorSymbol,
                        Name = indicator.Name,
                        IsNotResearched = true
                    });
                    continue;
                }

                companyIndicatorDto.Name = indicator.Name;
                companyIndicatorDto.IndicatorAssessments = new List<PIIndicatorAssessmentDto>();

                if (claimedIndicators != null)
                        companyIndicatorDto.HasAccess = claimedIndicators.Contains(indicator.Symbol);

                foreach (ProductInvolvementDataIndicator pias in ca.Indicators.Where(x => x.IndicatorSymbol == iass.IndicatorSymbol))
                {
                    //only for display purposes
                    if (!pias.LevelOfInvolvement.Stop.NearlyEq(100))
                    {
                        pias.LevelOfInvolvement.Stop -= 0.1;
                        pias.LevelOfInvolvement.Text = string.Format("{0}-{1}%", pias.LevelOfInvolvement.Start, pias.LevelOfInvolvement.Stop);
                    }

                    PIIndicatorAssessmentDto assDto = new PIIndicatorAssessmentDto()
                    {
                        IndicatorSymbol = pias.IndicatorSymbol,
                        CategorySymbol = pias.CategorySymbol,
                        HasLevelOfInvolvement = pias.HasLevelOfInvolvement,
                        LevelOfInvolvement = pias.LevelOfInvolvement,
                        HasOwnershipPercent = pias.HasOwnershipPercent,
                        OwnershipPercent = pias.OwnershipPercent,
                        StandardAnalysis = pias.StandardAnalysis,
                        Sources = pias.Sources,
                        LastEdited = pias.LastEdited,                        
                        Score = pias.Score                        
                    };

                    var cat = indicator.Categories.Where(x => x.Symbol == pias.CategorySymbol).FirstOrDefault();
                    assDto.CategorySymbolDescription = cat.Description;
                    companyIndicatorDto.IndicatorAssessments.Add(assDto);
                }

                //order indicator assessments
                companyIndicatorDto.IndicatorAssessments = companyIndicatorDto.IndicatorAssessments.OrderBy(x => x.CategorySymbol).ToList();
                result.Indicators.Add(companyIndicatorDto);
            }

            //order indicators
            result.Indicators = result.Indicators.OrderBy(x => x.Name).ToList();
            return result;
        }
    }
}
